all repos — caroster @ 194f9d892d23c5018e47649cd5f79d2d95d9eca9

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import {useTranslation} from 'react-i18next';
  3import Layout from '../../layouts/Default';
  4import Fab from '../../containers/Fab';
  5import CarColumns from '../../containers/CarColumns';
  6import NewCarDialog from '../../containers/NewCarDialog';
  7import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
  8import EventBar from '../../containers/EventBar';
  9import useToastStore from '../../stores/useToastStore';
 10import {initializeApollo} from '../../lib/apolloClient';
 11import ErrorPage from '../_error';
 12import {
 13  useUpdateEventMutation,
 14  Event as EventType,
 15  useEventByUuidQuery,
 16  EventByUuidDocument,
 17} from '../../generated/graphql';
 18import useEventStore from '../../stores/useEventStore';
 19import Loading from '../../containers/Loading';
 20
 21const POLL_INTERVAL = 10000;
 22
 23interface Props {
 24  event: EventType;
 25  eventUUID: string;
 26}
 27
 28const EventPage = props => {
 29  const {event} = props;
 30  const {t} = useTranslation();
 31
 32  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 33
 34  return <Event {...props} />;
 35};
 36
 37const Event = (props: Props) => {
 38  const {eventUUID} = props;
 39  const {t} = useTranslation();
 40  const addToast = useToastStore(s => s.addToast);
 41  const setEvent = useEventStore(s => s.setEvent);
 42  const eventUpdate = useEventStore(s => s.event);
 43  const setIsEditing = useEventStore(s => s.setIsEditing);
 44  const [updateEvent] = useUpdateEventMutation();
 45  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 46  const [openNewCar, toggleNewCar] = useReducer(i => !i, false);
 47  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 48    pollInterval: POLL_INTERVAL,
 49    variables: {uuid: eventUUID},
 50  });
 51
 52  useEffect(() => {
 53    if (event) setEvent(event as EventType);
 54  }, [event]);
 55
 56  const onSave = async e => {
 57    try {
 58      const {id, ...data} = eventUpdate;
 59      delete data.__typename;
 60      delete data.cars;
 61      await updateEvent({variables: {id, eventUpdate: data}});
 62      setIsEditing(false);
 63    } catch (error) {
 64      console.error(error);
 65      addToast(t('event.errors.cant_update'));
 66    }
 67  };
 68
 69  const onShare = async () => {
 70    if (!event) return null;
 71    // If navigator as share capability
 72    if (!!navigator.share)
 73      return await navigator.share({
 74        title: `Caroster ${event.name}`,
 75        url: `${window.location.href}`,
 76      });
 77    // Else copy URL in clipboard
 78    else if (!!navigator.clipboard) {
 79      await navigator.clipboard.writeText(window.location.href);
 80      addToast(t('event.actions.copied'));
 81      return true;
 82    }
 83  };
 84
 85  if (!event) return <Loading />;
 86
 87  return (
 88    <Layout
 89      pageTitle={t('event.title', {title: event.name})}
 90      menuTitle={t('event.title', {title: event.name})}
 91      displayMenu={false}
 92    >
 93      <EventBar
 94        event={event}
 95        onAdd={setIsAddToMyEvent}
 96        onSave={onSave}
 97        onShare={onShare}
 98      />
 99      <CarColumns toggleNewCar={toggleNewCar} />
100      <Fab onClick={toggleNewCar} open={openNewCar} aria-label="add-car" />
101      <NewCarDialog open={openNewCar} toggle={toggleNewCar} />
102      <AddToMyEventDialog
103        event={event}
104        open={isAddToMyEvent}
105        onClose={() => setIsAddToMyEvent(false)}
106      />
107    </Layout>
108  );
109};
110
111export async function getServerSideProps(ctx) {
112  const {uuid} = ctx.query;
113  const apolloClient = initializeApollo();
114  const {data = {}} = await apolloClient.query({
115    query: EventByUuidDocument,
116    variables: {uuid},
117  });
118  const {eventByUUID: event} = data;
119  const {host = ''} = ctx.req.headers;
120
121  return {
122    props: {
123      event,
124      eventUUID: uuid,
125      metas: {
126        title: event?.name || '',
127        url: `https://${host}${ctx.resolvedUrl}`,
128      },
129    },
130  };
131}
132
133export default EventPage;